package com.alinesno.cloud.common.core.orm.conditions;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.jpa.domain.Specification;

/**
 * 查询条件封装
 * @author LuoAnDong
 * @since 2018年11月20日 下午10:02:42
 */
public class QueryWrapper<T> implements Wrapper<T> {
	
	private static final Logger log = LoggerFactory.getLogger(QueryWrapper.class);

	@Override
	public Specification<T> handlerSpec(Map<String, Object> condition) {
		
		Specification<T> p = new Specification<T>() {

			/**
			 * 
			 */
			private static final long serialVersionUID = 1L;

			@Override
			public Predicate toPredicate(Root<T> root, CriteriaQuery<?> query, CriteriaBuilder cb) {
				List<Predicate> predicates = new ArrayList<Predicate>();

				if (condition != null) {

					Iterator<Map.Entry<String, Object>> iterator = condition.entrySet().iterator();
					while (iterator.hasNext()) {
						Map.Entry<String, Object> me = iterator.next();
						String[] keys = me.getKey().trim().split("\\|");
						Object value = me.getValue();

						log.debug("key = {} , value = {}", keys[0], value);

						if (keys.length == 1) {
							predicates.add(cb.equal(root.get(keys[0]), me.getValue()));
						} else if (keys.length >= 2) {
							String conditionKey = keys[1];
							String conditionVal = me.getValue()+"" ;

							switch (conditionKey) {
								case "like": predicates.add(cb.like(root.get(keys[0]),"%"+conditionVal+"%")) ;break;
								case "notLike": predicates.add(cb.notLike(root.get(keys[0]),"%"+conditionVal+"%")) ;break;
								case "likeLeft": predicates.add(cb.like(root.get(keys[0]),"%"+conditionVal)) ;break;
								case "likeRight": predicates.add(cb.like(root.get(keys[0]),conditionVal+"%")) ;break;
								case "le": predicates.add(cb.le(root.get(keys[0]),Double.parseDouble(conditionVal))) ;break;
								case "lt": predicates.add(cb.lt(root.get(keys[0]),Double.parseDouble(conditionVal))) ;break;
								case "ge": predicates.add(cb.ge(root.get(keys[0]),Double.parseDouble(conditionVal))) ;break;
								case "gt": predicates.add(cb.gt(root.get(keys[0]),Double.parseDouble(conditionVal))) ;break;
								default:predicates.add(cb.equal(root.<Object>get(keys[0]), me.getValue()));break;
							}

						}
					}
				}

				return query.where(predicates.toArray(new Predicate[predicates.size()])).getRestriction();
			}
		};

		return p;
	}

	@Override
	public Specification<T> mergeSpec(Specification<?> spec1, Specification<?> spec2) {
		return null;
	}

}
